package com.wwinsoft.modules.orm.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import com.wwinsoft.modules.orm.Page;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;

/**
 * @author: Tim.Chen
 * @since: 1.0
 */
@SuppressWarnings("unchecked")
public class SimpleJdbcDao<T> {

    protected SimpleJdbcTemplate jdbcTemplate;

    protected TransactionTemplate transactionTemplate;

    protected DataSource dataSource;

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Autowired
    public void setJdbcTemplate(SimpleJdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Autowired
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    public SimpleJdbcCall getSimpleJdbcCall(){
        return new SimpleJdbcCall(dataSource);
    }

    public Page<T> findPage(final Page<T> page, final String sql, RowMapper<T> rm, Map<String, Object> values) {
        Assert.notNull(page, "page不能为空");

        if (page.isAutoCount()) {
            long totalCount = countSqlResult(sql, values);
            page.setTotalCount(totalCount);
        }

        String pageSql = preparePageSql(sql);
        setPageParameterToMap(page, values);

        List result = jdbcTemplate.query(pageSql,rm,values);
        page.setResult(result);
        return page;
    }


    protected void setPageParameterToMap(Page<T> page,Map<String, Object> values){
        Integer startNum = (page.getPageNo()-1)*page.getPageSize() ;
        Integer endNum = page.getPageNo()*page.getPageSize() ;
        values.put("startNum",startNum) ;
        values.put("endNum",endNum) ;
    }


    protected long countSqlResult(final String sql, final Map<String, ?> values) {
        String countSql = prepareCountSql(sql);

        try {
            Long count = jdbcTemplate.queryForLong(countSql, values);
            return count;
        } catch (Exception e) {
            throw new RuntimeException("sql can't be auto count, sql is:" + countSql, e);
        }
    }


    private String prepareCountSql(String orgSql) {
        StringBuilder countSql = new StringBuilder();
        String preSql = "select count(*) from (";
        String sufSql = ")";
        countSql.append(preSql).append(orgSql).append(sufSql);
        return countSql.toString();
    }

    private String preparePageSql(String orgSql) {
        StringBuilder pageSql = new StringBuilder();
        String preSql = "select * from ( select row_.*, rownum rownum_ from (";
        String sufSql = ") row_  where rownum <= :endNum)  where rownum_ > :startNum";
        pageSql.append(preSql).append(orgSql).append(sufSql);
        return pageSql.toString();
    }



}
